iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Web 3

從以太坊白皮書理解 web 3 概念系列 第 26

從以太坊白皮書理解 web 3 概念 - Day25

  • 分享至 

  • xImage
  •  

從以太坊白皮書理解 web 3 概念 - Day25

NFT School Day 3 - Lazy Minting

今天將會透過 Lazy Minting 文章理解何謂 Lazy Minting 與實作 Lazy Minting

在主鏈鑄造一個 NFT 通常會花費很多,因為會需要手續費用來處理計算與儲存資料

然而透過一些比較新的技術可以把鑄造 NFT 這個處理程序延後到確認有要賣出 NFT 才去做。這樣做可以讓買 NFT 的人去負擔鑄造的費用,所以鑄造 NFT 的人不需要去鑄造費。

當被購買時才去鑄造 NFT 被稱作 Lazy Minting,這項技術降低了想要鑄造 NFT 的門檻。

在這邊將會使用 nft-school-example/lazy-minit 這個專案來做示範

clone 專案到 local

git clone https://github.com/ipfs-shipyard/nft-school-examples
cd nft-school-examples/lazy-minting
code . # or whichever editor you prefer

lazy minting 機制

lazy minting 不是直接透過呼叫 Contract 的 function 來產生 NFT, NFT 鑄造者會準備一個透過鑄造者密鑰對一些資料所產生出來的簽章。

這些簽章被稱作代金券可以用來贖回 NFT。這些簽章會包含所有關於該 NFT 的資料比如說價錢。這些簽章可以用來證明這個 NFT 鑄造者授權 NFT 的一些行為還有內容。

當購買者想要買一個 NFT,會呼叫 redeem function 來贖回這個簽章。當這個簽章被驗證是正確的並且購買者有被授權可以鑄造 NFT, NFT 就會根據這個簽章內容去製造出來並且轉移給購買者。

以下是贖回資料的範例

struct NFTVoucher {
  uint256 tokenId;
  uint256 minPrice;
  string uri;
  bytes signature;
}

贖回資料包含兩個位會紀錄再鏈上的資料:

  1. 唯一 token 識別代碼 tokenId
  2. token 資料 uri

minPrice 不會被紀錄在鏈上但是透過 redeem function 可以讓鑄造者在建立 NFT 時設定買賣價錢。假設 minPrice > 0 , 購買者需要在呼叫時傳送至少大於 minPrice 的錢來購買。

建立一個簽章過的贖回資料

為了確保贖回資料不會被撰改,這邊需要使用簽章的技術來驗證資料正確性

為了比較良好的使用者體驗,所以 Ethereum 發展出了一個針對結構化資料簽章規格 EIP-712

以下範例用了一個 Javascript 的類別 LazyMinter 就是使用上述 EIP-712 所實作的。因為簽章必須要屬於某個一發佈的 contract 實體,所以必須要提供一個已經發佈的 Contract address 與 ethers.js 的 Signer 用來做 NFT 鑄造的 private key 如下

const lazyminter = new LazyMinter({ myDeployedContract.address, signerForMinterAccount })

而建構贖回資料的邏輯 createVoucher 方法如下

async createVoucher(tokenId, uri, minPrice = 0) {
    const voucher = { tokenId, uri, minPrice }
    const domain = await this._signingDomain()
    const types = {
      NFTVoucher: [
        {name: "tokenId", type: "uint256"},
        {name: "minPrice", type: "uint256"},
        {name: "uri", type: "string"},  
      ]
    }
    const signature = await this.signer._signTypedData(domain, types, voucher)
    return {
      ...voucher,
      signature,
    }
  }

首先需要準備好要簽章的資料放在 const voucher 物件
然後根據 EIP-712 設定對應要簽章的 types

接著使用 _signTypedData 來計算簽章

然後把原本的資料跟簽章都包在 javascript 物件回傳回去

贖回 NFT 流程

為了 lazy minting , 必須要產生一個 Smart Contract 讓 NFT 購買者可以用來鑄造自己想要的 NFT 並且把 NFT 轉移到自己的 account 內,如下面 redeem:

  function redeem(address redeemer, NFTVoucher calldata voucher) public payable returns (uint256) {
    // make sure signature is valid and get the address of the signer
    address signer = _verify(voucher);

    // make sure that the signer is authorized to mint NFTs
    require(hasRole(MINTER_ROLE, signer), "Signature invalid or unauthorized");

    // make sure that the redeemer is paying enough to cover the buyer's cost
    require(msg.value >= voucher.minPrice, "Insufficient funds to redeem");

    // first assign the token to the signer, to establish provenance on-chain
    _mint(signer, voucher.tokenId);
    _setTokenURI(voucher.tokenId, voucher.uri);
    
    // transfer the token to the redeemer
    _transfer(signer, redeemer, voucher.tokenId);

    // record payment to signer's withdrawal balance
    pendingWithdrawals[signer] += msg.value;

    return voucher.tokenId;
  }

首先會使用 _verify 驗證要產生的NFT 簽章資料是否正確

接者會使用 OpenZeppelin 的 hasRole 來確認該簽章者是否俱備鑄造的能力

接著會確認 NFT 購買者是否傳輸大於 minPrice 的 ETH

如果都符合則開始根據簽章資料來產生 NFT 並且在鑄造完成後轉移到購買者帳戶


上一篇
從以太坊白皮書理解 web 3 概念 - Day24
下一篇
從以太坊白皮書理解 web 3 概念 - Day26
系列文
從以太坊白皮書理解 web 3 概念32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言